前言
昨天針對 Middleware 做一個初步基本介紹 (順序性、運作原理等等),今天會針對如何製作出一個簡易 Middleware 來分享基本與進階作法。
分享主軸
經過昨天後,都知道 Middleware 是在處理 ASP .NET Core 底層工作的中介,那他對於 ASP .NET Core 專案內,到底哪些算是所謂的 Middleware 呢 ?
在 ASP .NET Core 內,使用 CreateBuilder() 建立一個 WebApplicationBuilder 物件var builder = WebApplication.CreateBuilder(args);
然後所有要用到的服務,註冊到這邊 ( 把所有必要的服務註冊到 builder.Services 內,也就是IServiceCollection 內 )
白話點就是,Middleware 是如下中間的範圍都是var app = builder.Build();
....app.Run();
( builder.Build()會是 WebApplication 類別 )
app.Run() 就會執行 Kestrel 的意思
當 WebApplication 去註冊每一個 Middleware 的時候,就有順序性,不能擺錯,擺錯可能影響效能、安全性,所以專案內的 Middleware 不能隨意放置位置,要依照各個 Middleware 功能去決定放置順序
自己寫 Middleware 範例,兩種方法
public class RequestTimeoutMiddleware
{
private readonly RequestDelegate _next;
private readonly TimeSpan _timeout; //欲要限制的超時時間
public RequestTimeoutMiddleware(RequestDelegate next, TimeSpan timeout)
{
_next = next;
_timeout = timeout;
}
//處理每個 HTTP 請求
public async Task InvokeAsync(HttpContext context)
{
// 創建一個可以取消的
using (var cts = new CancellationTokenSource())
{
// 創建一個延遲任務,表示超時時間
var timeoutTask = Task.Delay(_timeout, cts.Token);
// 執行下一個Middleware
var requestTask = _next(context);
// 等待請求任務或超時任務中的任意一個完成
var completedTask = await Task.WhenAny(requestTask, timeoutTask);
// 如果超時任務
if (completedTask == timeoutTask)
{
// 設置 HTTP 狀態碼為 408(請求超時)
context.Response.StatusCode = StatusCodes.Status408RequestTimeout;
// 返回超時消息
await context.Response.WriteAsync("Request timed out.");
}
else
{
// 如果請求任務完成,取消超時任務
cts.Cancel();
// 等待請求任務完成
await requestTask;
}
}
}
}
Program.cs
var app = builder.Build();
// 設置請求超時時間為 5 秒
app.UseMiddleware<RequestTimeoutMiddleware>(TimeSpan.FromSeconds(5));
var app = builder.Build();
// 設置請求超時時間為 5 秒
app.Use(async (context, next) =>
{
using (var cts = new CancellationTokenSource())
{
var timeoutTask = Task.Delay(TimeSpan.FromSeconds(5), cts.Token);
var requestTask = next(context);
var completedTask = await Task.WhenAny(requestTask, timeoutTask);
if (completedTask == timeoutTask)
{
context.Response.StatusCode = StatusCodes.Status408RequestTimeout;
await context.Response.WriteAsync("Request timed out.");
}
else
{
cts.Cancel();
await requestTask;
}
}
});
app.Run();
兩種都可以跑,以上範例,自建一個Demo簡易的限制 Request 時間為5秒的 Middleware,若超過就返回,從這更可以得知 Middleware 可以做非常多事情,題外話 : 如果像是要取得更多應用層內的東西,這時候就可以使用 Filter 去實作 (今天不另外說明),會更為適合。
統整一下今日重點
今日結語
了解昨天與今天內容,個人覺得可以大大增加對於何謂 Middleware 與運用上的掌握更加彈性與可控,這些觀念真的都非常重要!
明日繼續努力,希望今天也有幫助到大家,謝謝。